package main

import (
	"github.com/fsnotify/fsnotify"
	"log"
	"os"
	"os/exec"
	"os/signal"
	path2 "path"
	"path/filepath"
	"strconv"
	"sync"
	"syscall"
	"time"
)

func main() {
	dir, e := os.Getwd()
	if e != nil {
		println("os.Getwd()", e.Error())
	}
	//启动文件变动监控
	go keepalive()
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal("NewWatcher failed: ", err)
	}
	mt := sync.Mutex{}
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				if event.Name[len(event.Name)-1:] == "~" {
					continue
				}
				if path2.Ext(event.Name) == "" {
					continue
				}
				mt.Lock()
				log.Printf("\n检测到文件改动，%s %s，即将重启程序\n", event.Name, event.Op)
				timeInt := time.Now().Unix()
				timeString := strconv.FormatInt(timeInt, 10)
				e := os.WriteFile("./last_change.txt", []byte(timeString), 0777)
				if e != nil {
					println("WriteFile", e.Error())
				}
				mt.Unlock()
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				log.Println("error:", err)
			}
		}
	}()
	// 遍历当前文件夹下的目录，将所有的目录添加但监听列表
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			watcher.Add(path)
		}
		return nil
	})

	//wait for signal to exit
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM)
	for {
		s := <-sigChan
		switch s {
		case syscall.SIGQUIT, syscall.SIGINT:
			e = watcher.Close()
			if e != nil {
				println(e)
			}

			cmd := exec.Command("pkill", "main")
			e = cmd.Run()
			println("程序退出")

			println("文件监听服务已停止")
			log.Println("SIGSTOP")
			return
		case syscall.SIGHUP:
			log.Println("SIGHUP")
			return
		case syscall.SIGKILL:
			log.Println("SIGKILL")
			return
		default:
			log.Println("default")
			return
		}
	}

	//Gracefully stop the consumer.

}

func keepalive() {
	for {
		timeTmp, e := os.ReadFile("./last_change.txt")
		if e != nil {
			println("读取文件监控数据", e.Error())
		}
		start(timeTmp)
	}
}

func start(lastChange []byte) {

	cmd := exec.Command("./main")

	e := cmd.Start()
	if e != nil {
		println("服务程序启动", e.Error())
	}
	for {
		timeTmp, e := os.ReadFile("./last_change.txt")
		if e != nil {
			println("读取临时文件", e.Error())
		}
		if string(lastChange) != string(timeTmp) {
			println("检测到文件变更")
			exec.Command("pkill", "main").Run()
			println("程序退出")
			return
		}
		//println(time.Now().String())
		time.Sleep(2 * time.Second)
	}
}
